package it.antonio.ilpizze.aop.advice;

import it.antonio.ilpizze.aop.Advice;
import it.antonio.ilpizze.aop.Invocation;
import it.antonio.ilpizze.aop.util.DelegateInvocation;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class AndAdvice implements Advice{
	
	private List<Advice> advices;
	
	public AndAdvice(Advice[] advices) {
		super();
		this.advices = Arrays.asList(advices);
	}


	@Override
	public Object onMethod(Invocation invocation) throws Throwable {
		InnerInvocation inner = new InnerInvocation(invocation, advices.iterator());
		return inner.proceed();
	}
	
	private class InnerInvocation extends DelegateInvocation{
		
		private Iterator<Advice> advices;
		
		public InnerInvocation(Invocation delegate, Iterator<Advice> advices) {
			super(delegate);
			this.advices = advices;
		}

		@Override
		public Object proceed() throws Throwable {
			 
			while(advices.hasNext()){
                 Advice advice = advices.next();
                 return advice.onMethod(this);
			 }
         
			 return delegate.proceed();
		}
		
	}
}
